package org.totoro.structure.queue.impl;

import org.totoro.structure.queue.Queue;

/**
 * 循环队列
 *
 * @author daocr
 * @date 2020/3/22
 */
public class CycleQueue<E> implements Queue<E> {

    private Object[] queue;

    /**
     * 队列头部索引
     */
    private int front;

    /**
     * 队列尾部索引
     */
    private int tail;

    private int size;

    private int capacity;

    public CycleQueue(Integer capacity) {
        this.capacity = capacity + 1;
        this.queue = new Object[this.capacity];
    }

    @Override
    public void enqueue(E e) {
        int tailIndex = this.calculationTail();

        if ((tailIndex) == front) {
            throw new OutOfMemoryError("超过最大容量");
        }

        queue[tail] = e;

        tail = tailIndex;

        size++;
    }

    /**
     * 计算  tail 索引
     *
     * @return
     */
    public int calculationTail() {
        // 求余数
        return (tail + 1) % capacity;

    }

    /**
     * 计算  front 索引
     *
     * @return
     */
    public int calculationFront() {
        // 求余数
        return (front + 1) % capacity;

    }

    @Override
    public E dequeue() {

        int calculationFront = calculationFront();

        if (front == tail) {
            return null;
        }

        E element = (E) queue[front];
        // gc
        queue[front] = null;
        front = calculationFront;
        size--;

        return element;
    }


    @Override
    public E getFirst() {
        return (E) queue[front];
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    public static void main(String[] args) {


        CycleQueue<Integer> integerCycleQueue = new CycleQueue<Integer>(10);

        for (int i = 0; i < 10; i++) {
            integerCycleQueue.enqueue(i);
        }

        for (int i = 0; i < 5; i++) {
            System.out.println(integerCycleQueue.dequeue());
        }

        for (int i = 0; i < 5; i++) {
            integerCycleQueue.enqueue(i + 10);
        }


        System.out.println("---------");

        Integer dequeue = null;

        while ((dequeue = integerCycleQueue.dequeue()) != null) {
            System.out.println(dequeue);
        }


    }
}
